#include <iostream>
#include <vector>
using namespace std;

void A_B(int order);
void R_K();
void BDFs(int order);
void A_M(int order);
  
typedef enum ProductTypeTag
{
 TypeA_B1,TypeA_B2,TypeA_B3,TypeA_B4,
  TypeA_M2,TypeA_M3,TypeA_M4,TypeA_M5,
  TypeBDFs1,TypeBDFs2,TypeBDFs3,TypeBDFs4,
  TypeR_K
}PRODUCTTYPE;
  
// Here is the product class
class Product
{
public:
  virtual void Show() = 0;
};
  
class ProductA_B1 : public Product
{
public:
  void Show()
  {
    A_B(1);
  }
};

class ProductA_B2 : public Product
{
public:
  void Show()
  {
    A_B(2);
  }
};

class ProductA_B3 : public Product
{
public:
  void Show()
  {
    A_B(3);
  }
};

class ProductA_B4 : public Product
{
public:
  void Show()
  {
    A_B(4);
  }
};
  
class ProductA_M2 : public Product
{
public:
  void Show()
  {
    A_M(1);
  }
};

class ProductA_M3 : public Product
{
public:
  void Show()
  {
    A_M(2);
  }
};

class ProductA_M4 : public Product
{
public:
  void Show()
  {
    A_M(3);
  }
};

class ProductA_M5 : public Product
{
public:
  void Show()
  {
    A_M(4);
  }
};
  
class ProductBDFs1 : public Product
{
public:
  void Show()
  {
    BDFs(1);
  }
};

class ProductBDFs2 : public Product
{
public:
  void Show()
  {
    BDFs(2);
  }
};

class ProductBDFs3 : public Product
{
public:
  void Show()
  {
    BDFs(3);
  }
};

class ProductBDFs4 : public Product
{
public:
  void Show()
  {
    BDFs(4);
  }
};

class ProductR_K : public Product
{
public:
  void Show()
  {
    R_K();
  }
};

// Here is the Factory class
class Factory
{
public:
  Product* CreateProduct(PRODUCTTYPE type)
  {
    switch (type)
    {
    case TypeA_B1:
      return new ProductA_B1();

    case TypeA_B2:
      return new ProductA_B2();

    case TypeA_B3:
      return new ProductA_B3();

    case TypeA_B4:
      return new ProductA_B4();
  
    case TypeA_M2:
      return new ProductA_M2();

    case TypeA_M3:
      return new ProductA_M3();

    case TypeA_M4:
      return new ProductA_M4();

    case TypeA_M5:
      return new ProductA_M5();
  
    case TypeBDFs1:
      return new ProductBDFs1();

        case TypeBDFs2:
      return new ProductBDFs2();

        case TypeBDFs3:
      return new ProductBDFs3();

        case TypeBDFs4:
      return new ProductBDFs4();

    case TypeR_K:
      return new ProductR_K();  
  
    default:
      return NULL;
    }
  }
};
  
int main(int argc, char *argv[])
{
  // First, create a factory object
  Factory *ProductFactory = new Factory();
  Product *productObjA_B1 = ProductFactory->CreateProduct(TypeA_B1);
  if (productObjA_B1 != NULL)
    productObjA_B1->Show();

    Product *productObjA_B2 = ProductFactory->CreateProduct(TypeA_B2);
  if (productObjA_B2 != NULL)
    productObjA_B2->Show();

    Product *productObjA_B3 = ProductFactory->CreateProduct(TypeA_B3);
  if (productObjA_B3 != NULL)
    productObjA_B3->Show();

    Product *productObjA_B4 = ProductFactory->CreateProduct(TypeA_B4);
  if (productObjA_B4 != NULL)
    productObjA_B4->Show();
  
  Product *productObjA_M2 = ProductFactory->CreateProduct(TypeA_M2);
  if (productObjA_M2 != NULL)
    productObjA_M2->Show();

    Product *productObjA_M3 = ProductFactory->CreateProduct(TypeA_M3);
  if (productObjA_M3 != NULL)
    productObjA_M3->Show();

    Product *productObjA_M4 = ProductFactory->CreateProduct(TypeA_M4);
  if (productObjA_M4 != NULL)
    productObjA_M4->Show();

    Product *productObjA_M5 = ProductFactory->CreateProduct(TypeA_M5);
  if (productObjA_M5 != NULL)
    productObjA_M5->Show();
  
  Product *productObjBDFs1 = ProductFactory->CreateProduct(TypeBDFs1);
  if (productObjBDFs1 != NULL)
    productObjBDFs1->Show();

   Product *productObjBDFs2 = ProductFactory->CreateProduct(TypeBDFs2);
  if (productObjBDFs2 != NULL)
    productObjBDFs2->Show();

       Product *productObjBDFs3 = ProductFactory->CreateProduct(TypeBDFs3);
  if (productObjBDFs3 != NULL)
    productObjBDFs3->Show();

       Product *productObjBDFs4 = ProductFactory->CreateProduct(TypeBDFs4);
  if (productObjBDFs4 != NULL)
    productObjBDFs4->Show();
  

  Product *productObjR_K = ProductFactory->CreateProduct(TypeR_K);
  if (productObjR_K != NULL)
    productObjR_K->Show();
  
  delete ProductFactory;
  ProductFactory = NULL;
  
  delete productObjA_B1;
  productObjA_B1 = NULL;

  delete productObjA_B2;
  productObjA_B2 = NULL;

  delete productObjA_B3;
  productObjA_B3 = NULL;

  delete productObjA_B4;
  productObjA_B4 = NULL;
  
  delete productObjA_M2;
  productObjA_M2 = NULL;

    delete productObjA_M3;
  productObjA_M3 = NULL;

    delete productObjA_M4;
  productObjA_M4 = NULL;

    delete productObjA_M5;
  productObjA_M5 = NULL; 
  
  delete productObjBDFs1;
  productObjBDFs1 = NULL;

    delete productObjBDFs2;
  productObjBDFs2 = NULL;

    delete productObjBDFs3;
  productObjBDFs3 = NULL;

    delete productObjBDFs4;
  productObjBDFs4 = NULL;

  delete productObjR_K;
  productObjR_K = NULL;
  
  return 0;
}
